﻿using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Web;
using Enyim.Caching;
using Ayatta.Contract;
using Ayatta.Common;
using System.Web.Mvc;
using Newtonsoft.Json;
using Web.Core.Security;
using Web.Seller.Models;
using Web.Core.Extensions;
using System.Web.WebPages;
using Ayatta.Contract.Domain;
using Ayatta.Common.Extension;
using System.Collections.Generic;
using Ayatta.Contract.Component;
using Microsoft.Security.Application;

namespace Web.Seller.Controllers
{
    public class ItemController : BaseController
    {
        public ItemController(Lazy<IInfrastructureService> infrastructure, Lazy<IPassportService> passport, Lazy<IAccountService> account, Lazy<IStoreService> store, Lazy<ITradeService> trade, Lazy<IPlayService> play, Lazy<IMiscService> misc, Lazy<IExtraService> extra, IMemcachedClient memcachedClient)
            : base(infrastructure, passport, account, store, trade, play, misc, extra, memcachedClient)
        {
        }

        public ActionResult Index(int page = 1, int size = 20, byte param = 0, string keyword = null, string outerId = null, int? categoryRootId = null, decimal? priceFrom = null, decimal? priceTo = null, int? saleFrom = null, int? saleTo = null, string[] orderBy = null)
        {
            var id = keyword.AsInt(0);
            var identity = User.Identity.Identity();
            var name = id > 0 ? string.Empty : keyword;

            var model = new ItemControllerModel.Index();
            var dic = model.GetOrderByDic(orderBy);
            model.Param = param;
            model.Keyword = keyword;
            model.OuterId = outerId;
            model.CategoryRootId = categoryRootId;
            model.PriceFrom = priceFrom;
            model.PriceTo = priceTo;
            model.SaleFrom = saleFrom;
            model.SaleTo = saleTo;
            model.Items = Store.Value.ProductItemPagedList(page, size, param, identity.Id, id, name, outerId, categoryRootId, priceFrom, priceTo, saleFrom, saleTo, dic).ToPagedList(page, size);

            return View(model);
        }

        #region 商品名称
        /// <summary>
        /// 更新商品名称
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public ActionResult Name(int param)
        {
            var model = Store.Value.ProductItemNameGet(param);
            return PartialView(model);
        }

        /// <summary>
        /// 更新商品名称
        /// </summary>
        /// <param name="param"></param>
        /// <param name="name"></param>
        /// <param name="subName"></param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult Name(int param, string name, string subName)
        {
            var identity = User.Identity.Identity();
            var result = new MagicKit<string, string>();
            var status = result.Status = Store.Value.ProductItemNameUpdate(param, identity.Id, name, subName);
            if (status)
            {
                result.Data = name;
                result.Extra = subName;
            }
            else
            {
                result.Message = "更新商品名称失败！";
            }
            return Json(result);
        }

        #endregion

        #region 商品价格
        /// <summary>
        /// 商品价格
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public ActionResult Price(int param)
        {
            var identity = User.Identity.Identity();
            var model = Store.Value.ProductItemPriceQuantityGet(param, identity.Id);
            return PartialView(model);
        }

        /// <summary>
        /// 商品价格更新
        /// </summary>
        /// <param name="param"></param>
        /// <param name="avgprice"></param>
        /// <param name="id"></param>
        /// <param name="price"></param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult Price(int param, decimal avgprice, int[] id = null, decimal[] price = null)
        {
            var status = false;
            var len = id == null ? 0 : id.Length;

            var identity = User.Identity.Identity();
            var result = new MagicKit<string>();
            if (id != null && price != null)
            {
                var dic = new Dictionary<int, decimal>();
                for (var i = 0; i < len; i++)
                {
                    var key = id[i];
                    var value = price[i];
                    dic.Add(key, value);
                }

                var min = dic.Min(o => o.Value);
                var max = dic.Max(o => o.Value);
                if (avgprice >= min && avgprice <= max)
                {
                    status = result.Status = Store.Value.ProductItemPriceUpdate(param, identity.Id, avgprice, dic);
                }
                else
                {
                    result.Message = "商品价格请设置在合理区间内！";
                }
            }
            else
            {
                status = result.Status = Store.Value.ProductItemPriceUpdate(param, identity.Id, avgprice, null);
            }
            if (status)
            {
                result.Data = avgprice.ToString("N");
            }
            else
            {
                result.Message = "更新价格失败！";
            }
            return Json(result);
        }

        #endregion

        #region 商品库存
        /// <summary>
        /// 商品库存
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public ActionResult Quantity(int param)
        {
            var identity = User.Identity.Identity();
            var model = Store.Value.ProductItemPriceQuantityGet(param, identity.Id);
            return PartialView(model);
        }

        /// <summary>
        /// 商品库存更新
        /// </summary>
        /// <param name="param"></param>
        /// <param name="inventory"></param>
        /// <param name="id"></param>
        /// <param name="quantity"></param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult Quantity(int param, int inventory=0, int[] id = null, int[] quantity = null)
        {
            bool status;
            var total = inventory;
            var len = id == null ? 0 : id.Length;

            var identity = User.Identity.Identity();
            var result = new MagicKit<string>();
            if (id != null && quantity != null)
            {
                var dic = new Dictionary<int, int>();
                for (var i = 0; i < len; i++)
                {
                    var key = id[i];
                    var value = quantity[i];
                    dic.Add(key, value);
                }

                total = dic.Sum(o => o.Value);
               
                 status = result.Status = Store.Value.ProductItemQuantityUpdate(param, identity.Id, total, dic);
            }
            else
            {
                status = result.Status = Store.Value.ProductItemQuantityUpdate(param, identity.Id, total, null);
            }
            if (status)
            {
                result.Data = total.ToString();
            }
            else
            {
                result.Message = "更新库存失败！";
            }
            return Json(result);
        }
        #endregion

        #region 添加商品

        public ActionResult Create()
        {
            var model = new ItemControllerModel.Create();
            model.Groups = CategoryGroupList(0);
            model.Categories = ProductCategoryList(0);
            return View(model);
        }

        [HttpPost, ValidateInput(false)]
        public ActionResult Create(FormCollection form)
        {
            var time = DateTime.Now;
            const string prefix = "prop.";
            var item = new ProductItem();
            var result = new MagicKit<string>();
            var identity = User.Identity.Identity();

            var productId = form[prefix + "productid"].AsInt(0);
            var hierarchyId = form[prefix + "hierarchyid"].Split('/');
            int categoryId = 0, categoryRootId = 0;
            var categoryMiddleId = string.Empty;
            for (var i = 0; i < hierarchyId.Length; i++)
            {
                if (i == 0)
                {
                    categoryRootId = hierarchyId[i].AsInt();
                }
                else if (i == hierarchyId.Length - 1)
                {
                    categoryId = hierarchyId[i].AsInt();
                }
                else if (i != hierarchyId.Length - 2)
                {
                    categoryMiddleId += hierarchyId[i] + "/";
                }
                else
                {
                    categoryMiddleId += hierarchyId[i];
                }
            }
            if (categoryRootId < 0 || categoryId < 0)
            {
                result.Data = "category";
                result.Message = "类目错误！";

                return Json(result);
            }
            var outerId = form[prefix + "outerId"] ?? string.Empty;

            var name = form[prefix + "name"];
            if (name.IsNullOrEmpty() || name.Length > 30)
            {
                result.Data = "name";
                return Json(result);
            }

            var subName = form[prefix + "subName"];
            if (!subName.IsNullOrEmpty() && subName.Length > 30)
            {
                result.Data = "subName";
                return Json(result);
            }

            decimal itemPrice = 0;
            var priceField = form[prefix + "price"];
            if (priceField.IsNullOrEmpty() || !decimal.TryParse(priceField, out itemPrice) || (itemPrice < 0 || itemPrice > 99999999))
            {
                result.Data = "price";
                return Json(result);
            }

            var itemQuantity = 0;
            var quantityField = form[prefix + "quantity"];
            if (quantityField.IsNullOrEmpty() || !int.TryParse(quantityField, out itemQuantity) || (itemQuantity < 0 || itemQuantity > 99999999))
            {
                result.Data = "quantity";
                return Json(result);
            }

            var desc = form[prefix + "desc"];
            if (desc.IsNullOrEmpty() || (desc.Length < 5 || desc.Length > 20000))
            {
                result.Data = "desc";
                return Json(result);
            }

            var subStock = form[prefix + "subStock"].As<byte>();

            var isTiming = false;
            var onlineTime = time;
            var itemStatus = ProductItemStatus.Online;
            var onlineTimeField = form[prefix + "onlineTime"];
            if (onlineTimeField == "0" || onlineTimeField == "1")
            {
                if (onlineTimeField == "1")
                {
                    itemStatus = ProductItemStatus.Offline;
                }
            }
            else if (!DateTime.TryParse(onlineTimeField, out onlineTime))
            {
                //var error = new { name = prefix + "onlineTime", message = "请选择日期及时间！" };
                //errors.Add(error);
                result.Data = "onlinetime";
                result.Message = "请选择日期及时间！";
                return Json(result);
            }
            else
            {
                isTiming = true;
            }

            var props = ProductCategoryPropList(categoryId);
            var saleProps = props.Where(o => o.IsSaleProp);
            var colorProps = props.Where(o => o.IsColorProp);
            var otherProps = props.Where(o => !o.IsSaleProp && !o.IsColorProp);

            var propValues = ProductCategoryPropValueList(categoryId);

            var skus = new List<ProductItemSku>();
            var saleKeys = (from prop in saleProps let temp = prop select propValues.Where(o => o.PropId == temp.Id).Select(o => prop.Id + ":" + o.Id).ToArray()).ToList();
            var skuKeys = GetAllSkuKeys(saleKeys);
            if (!skuKeys.IsNullOrEmpty())
            {
                foreach (var skuKey in skuKeys)
                {
                    if (skuKey.IsNullOrEmpty()) continue;
                    var priceParam = "sku.pric." + skuKey;
                    var quantityParam = "sku.quantity." + skuKey;
                    var outerIdParam = "sku.outerid." + skuKey;
                    int quantity;
                    decimal price;

                    var priceVal = form[priceParam];
                    var quantityVal = form[quantityParam];
                    var outerIdVal = form[outerIdParam];
                    if (priceVal.IsNullOrEmpty() || !decimal.TryParse(priceVal, out price) || quantityVal.IsNullOrEmpty() || !int.TryParse(quantityVal, out quantity))
                    {
                        continue;
                    }
                    var sku = new ProductItemSku();
                    var nvs = skuKey.Split(';');
                    var propstr = string.Empty;
                    foreach (var nv in nvs)
                    {
                        var pid = nv.Split(':')[0].AsInt();
                        var vid = nv.Split(':')[1].AsInt();
                        var pn = props.First(o => o.Id == pid).Name;
                        var vn = propValues.First(o => o.Id == vid).Name;
                        propstr += string.Format("{0}:{1}:{2}:{3};", pid, vid, pn, vn);
                    }
                    sku.UserId = identity.Id;
                    sku.ProductId = productId;
                    sku.CategoryId = categoryId;
                    sku.CategoryRootId = categoryRootId;
                    sku.CategoryMiddleId = categoryMiddleId;
                    sku.OuterId = outerIdVal;
                    sku.PropId = skuKey;
                    sku.PropStr = propstr.TrimEnd(';');
                    sku.Price = price;
                    sku.Quantity = quantity;
                    sku.Sale = 0;
                    sku.Status = 0;
                    sku.CreatedOn = time;
                    sku.ModifiedOn = time;
                    skus.Add(sku);
                }
                /*
                if (skus.Count < 1)
                {
                    result.Data = "sku";
                    result.Message = "请选择商品规格！";
                    return Json(result);
                }
                 */
            }

            var propImgDic = new Dictionary<string, string>();
            foreach (var prop in colorProps)
            {
                var pid = prop.Id;
                var values = propValues.Where(o => o.PropId == pid);
                foreach (var value in values)
                {
                    var key = prop.Id + ":" + value.Id;
                    var img = prefix + "img." + key;
                    var file = form[img];
                    if (!file.IsNullOrEmpty())
                    {
                        //ProductImageUpload(file, identity.Id, true, propImgDic);
                        propImgDic.Add(key, file);

                    }
                }
            }
            var itemImgDic = new Dictionary<int, string>();
            for (int i = 1, j = 1; i < 6; i++)
            {
                var img = prefix + "img." + i;
                var file = form[img];
                if (!file.IsNullOrEmpty())
                {
                    itemImgDic.Add(j, file);
                    j += 1;
                }
            }
            var inputIdBuilder = new StringBuilder();
            var inputStrBuilder = new StringBuilder();
            var propIdBuilder = new StringBuilder(props.Count);
            var propStrBuilder = new StringBuilder(props.Count);

            foreach (var prop in otherProps)
            {
                var pvid = form[prefix + prop.Id];
                if (pvid.IsNullOrEmpty())
                {
                    continue;
                }
                if (prop.Type == PropType.Text)
                {
                    inputIdBuilder.AppendFormat("{0},", prop.Id);
                    inputStrBuilder.AppendFormat("{0},", pvid);
                }
                else if (prop.Type == PropType.MultiCheck || prop.Type == PropType.MultiCheckText)
                {
                    var kvs = pvid.Split(',');
                    if (kvs.Length > 0)
                    {
                        foreach (var kv in kvs)
                        {
                            var vid = kv.Split(':')[1].AsInt();
                            var val = propValues.FirstOrDefault(o => o.Id == vid);
                            if (val == null) continue;
                            propIdBuilder.AppendFormat("{0}:{1};", prop.Id, val.Id);
                            propStrBuilder.AppendFormat("{0}:{1}:{2}:{3};", prop.Id, val.Id, prop.Name, val.Name);
                        }
                    }
                }
                else
                {
                    var vid = pvid.Split(':')[1].AsInt();
                    var val = propValues.FirstOrDefault(o => o.Id == vid);
                    if (val != null)
                    {
                        propIdBuilder.AppendFormat("{0}:{1};", prop.Id, val.Id);
                        propStrBuilder.AppendFormat("{0}:{1}:{2}:{3};", prop.Id, val.Id, prop.Name, val.Name);
                    }
                }
                if (prop.Id == 20000)
                {
                    var vid = pvid.Split(':')[1].AsInt();
                    var val = propValues.FirstOrDefault(o => o.Id == vid);
                    if (val != null)
                    {
                        item.BrandId = vid;
                        item.BrandName = val.Name;
                    }
                }
            }
            item.Quantity = itemQuantity;
            if (skus.Count > 0)
            {
                if (itemPrice < skus.Min(o => o.Price) || itemPrice > skus.Max(o => o.Price))
                {
                    result.Data = "price";
                    return Json(result);
                }
                item.Quantity = skus.Sum(o => o.Quantity);
            }

            item.UserId = identity.Id;
            item.ProductId = productId;
            item.CategoryId = categoryId;
            item.CategoryRootId = categoryRootId;
            item.CategoryMiddleId = categoryMiddleId;
            item.OuterId = outerId;
            item.Name = name.StripHtml();
            item.SubName = subName.StripHtml();
            item.Price = itemPrice;

            item.RewardRate = 0.5m;
            item.PropId = propIdBuilder.ToString().TrimEnd(';');
            item.PropStr = propStrBuilder.ToString().TrimEnd(';');
            item.PropAlias = string.Empty;
            item.InputId = inputIdBuilder.ToString().TrimEnd(',');
            item.InputStr = inputStrBuilder.ToString().TrimEnd(',');
            var imgs = GetItemImgs(identity.Id, itemImgDic);
            var propImgs = GetPropImgs(identity.Id, propImgDic);
            item.Picture = imgs.FirstOrDefault().Value;
            item.ItemImg = JsonConvert.SerializeObject(imgs);
            item.PropImg = JsonConvert.SerializeObject(propImgs);
            item.Weight = 0M;
            item.Size = string.Empty;
            item.Description = Sanitizer.GetSafeHtmlFragment(desc);
            item.IsVirtual = false;

            item.AutoFill = 0;
            item.SubStock = subStock;
            item.Showcase = 0;
            item.IsTiming = isTiming;
            item.OnlineTime = onlineTime;
            item.OfflineTime = time.AddYears(2);
            item.Relation = string.Empty;
            item.Status = itemStatus;
            item.CreatedBy = User.Identity.Name;
            item.CreatedOn = time;
            item.ProductItemSkus = skus;


            var magic = Store.Value.ProductItemCreate(item);

            var status = result.Status = magic.Status;
            if (status)
            {
                result.Data = magic.Data.ToString();
            }
            else
            {
                result.Message = magic.Message;
            }

            return Json(result);
        }

        protected string[] GetAllSkuKeys(IList<string[]> keys)
        {
            var len = keys.Count;
            if (len < 1)
            {
                return null;
            }
            if (len == 1)
            {
                return keys[0];
            }
            if (len > 1)
            {
                var first = keys[0];
                var next = keys[1];
                var array = new List<string>();
                foreach (var t in first)
                {
                    array.AddRange(next.Select(x => t + ';' + x));
                }
                if (len == 2)
                {
                    return array.ToArray();
                }
                keys.RemoveAt(0);
                keys.RemoveAt(1);
                keys[0] = array.ToArray();

                keys[0] = GetAllSkuKeys(keys);
            }
            return keys[0];
        }

        private Dictionary<string, string> GetPropImgs(int userId, Dictionary<string, string> dic)
        {
            var result = new Dictionary<string, string>();
            var proxy = new ServiceClientProxy<IUploadService>("FileUploadService");
            foreach (var o in dic)
            {
                var magic = ProductImageUpload(proxy, o.Value, userId, true);
                if (magic.Status)
                {
                    result.Add(o.Key, magic.Message);
                }
            }
            return result;
        }
        private Dictionary<int, string> GetItemImgs(int userId, Dictionary<int, string> dic)
        {
            var isMain = true;
            var result = new Dictionary<int, string>();
            var proxy = new ServiceClientProxy<IUploadService>("FileUploadService");
            foreach (var o in dic)
            {
                var magic = ProductImageUpload(proxy, o.Value, userId, false, isMain);
                if (magic.Status)
                {
                    result.Add(o.Key, magic.Message);
                }
                isMain = false;
            }
            return result;
        }
        public MagicKit ProductImageUpload(ServiceClientProxy<IUploadService> proxy, string file, int userId, bool isPropImg, bool isMain = false)
        {
            var magic = new MagicKit();
            try
            {
                var path = Server.MapPath("/temp/" + file);
                var fileName = Path.GetFileName(path);
                var extension = Path.GetExtension(path);
                var folder = string.Format("{0}/img/product/", userId);
                using (var stream = System.IO.File.OpenRead(path))
                {
                    var fileInfo = new UploadFile(stream, fileName, folder);
                    var prefix = "http://asset.ayatta.com/" + folder;

                    magic.Message = prefix + fileName + ".l" + extension;

                    if (isPropImg)
                    {
                        proxy.Invoke(o => o.ProductPropImageUpload(fileInfo));
                    }
                    else
                    {
                        if (isMain)
                        {
                            fileInfo.Extra = "1";//主图片需生成各种尺寸的缩略图
                        }
                        proxy.Invoke(o => o.ProductItemImageUpload(fileInfo));
                        using (var img = System.Drawing.Image.FromStream(stream))
                        {
                            if (img.Width >= 800 || img.Height >= 800)
                            {
                                magic.Message = prefix + fileName + ".xl" + extension;
                            }
                        }
                    }
                    magic.Status = true;
                }
            }
            catch (Exception e)
            {
                magic.Message = e.Message;
            }
            return magic;
        }
        /// <summary>
        /// 商品图片上传
        /// </summary>
        /// <param name="param"></param>
        /// <param name="prop"></param>
        /// <param name="image"></param>
        /// <returns></returns>
        public ActionResult Upload(int param = 0, string prop = null, HttpPostedFileBase image = null)
        {
            var result = new MagicKit<string, string>();
            var identity = User.Identity.Identity();
            if (Request.IsAuthenticated)
            {
                if (image != null)
                {
                    var extension = Path.GetExtension(image.FileName.ToLower());
                    var extensions = new[] { ".gif", ".png", ".jpg", ".jpeg" };
                    if (extension.IsIn(extensions))
                    {
                        var size = image.ContentLength;
                        if (size > 1024 * 1024)
                        {
                            result.Message = "图片类型只能为gif,png,jpg,jpeg，且大小不超过1M！";
                        }
                        else
                        {
                            var name = Guid.NewGuid() + extension;
                            var filename = Server.MapPath("/temp/" + name);
                            try
                            {
                                image.SaveAs(filename);//保存到临时目录
                                result.Status = true;
                                result.Data = name;
                                if (param == 0 && !string.IsNullOrEmpty(prop))
                                {
                                    result.Extra = prop.Replace(':', '-');
                                }
                                if (param != 0 && prop.IsNullOrEmpty())
                                {
                                    result.Extra = param.ToString();
                                }
                            }
                            catch (Exception e)
                            {
                                result.Message = e.Message;
                            }
                        }
                    }
                    else
                    {
                        result.Message = "图片类型只能为gif,png,jpg,jpeg，且大小不超过1M！";
                    }
                }
                else
                {
                    result.Message = "请选择图片！";
                }
            }
            else
            {
                result.Message = "身份验证失败，请重新登录！";
            }
            var js = string.Format("<script type='text/javascript'>document.domain ='ayatta.com';window.parent.imageUploadCallback({0});</script>", JsonConvert.SerializeObject(result));
            return Content(js);
        }

        #endregion
    }
}
